package com.capsulode.excel.conversion.impl;

import com.capsulode.excel.conversion.Converter;
import com.capsulode.excel.exception.CellTypeNotExpectException;
import com.capsulode.excel.exception.ConversionFailException;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 货币转换. 将`元`转换为`分`.
 */
public class RmbConverter implements Converter {
    private static final BigDecimal d100 = new BigDecimal("100.00");
    private final Class type;

    public RmbConverter(Class type) {
        this.type = type;
    }

    @Override
    public Object convert(Cell cell) throws ConversionFailException, CellTypeNotExpectException {
        if (CellType.NUMERIC.equals(cell.getCellTypeEnum())
                || CellType.FORMULA.equals(cell.getCellTypeEnum())) {
            int fen = convertYuanToFen(cell.getNumericCellValue());
            return convertToRequiredType(fen, type, cell.getRowIndex(), cell.getColumnIndex());
        }
        if (CellType.BLANK.equals(cell.getCellTypeEnum())) {
            return null;
        }
        if (CellType.STRING.equals(cell.getCellTypeEnum())) {
            String trim = cell.getStringCellValue().trim();
            if (trim.isEmpty()) {
                return null;
            }
            double d;
            try {
                d = Double.parseDouble(trim);
            } catch (NumberFormatException ex) {
                throw new CellTypeNotExpectException(cell.getRowIndex(), cell.getColumnIndex(), "无效的数字：" + cell, ex);
            }
            int fen = convertYuanToFen(d);
            return convertToRequiredType(fen, type, cell.getRowIndex(), cell.getColumnIndex());
        }

        throw new CellTypeNotExpectException(cell.getRowIndex(), cell.getColumnIndex());
    }

    @Override
    public void serialize(Object value, Cell cell) throws ConversionFailException, CellTypeNotExpectException {
        Integer val = null;
        if (value instanceof Number) {
            val = ((Number) value).intValue();
        }
        if (value instanceof CharSequence) {
            val = Integer.parseInt(value.toString());
        }
        if (val == null) {
            throw new CellTypeNotExpectException(cell.getRowIndex(), cell.getColumnIndex());
        }
        double yuan = convertFenToYuan(val);
        cell.setCellValue(yuan);
    }

    private Object convertToRequiredType(int fen, Class type, int row, int column) throws ConversionFailException {
        try {
            return ConvertUtils.convert(fen, type);
        } catch (ConversionException ex) {
            throw new ConversionFailException(row, column, "货币字段类型无效", ex);
        }
    }

    private int convertYuanToFen(double d) {
        return new BigDecimal(d).multiply(d100).intValue();
    }

    private double convertFenToYuan(int d) {
        return new BigDecimal(d).setScale(2).divide(d100, RoundingMode.HALF_UP).doubleValue();
    }

}
